#pragma once

#include <boost/type_traits.hpp>
#include <boost/mpl/if.hpp>

#include "internal/traits.hpp"

namespace tb {

namespace safe {

template <OwnerType, typename TypeTag>
template SafeObjectImpl{
public:
	SafeObjectImpl() {}

	virtual ~SafeObjectImpl() {
		WaitAndDie();
	}

	void WaitAndDie() {
		_owner.WaitAndDie();
	}

	bool TryDie() {
		return _owner.TryDie();
	}

	void WaitAndForceDie() {
		_owner.WaitAndForceDie();
	}

	bool TryForceDie() {
		return _owner.TryForceDie();
	}

	const OwnerType &GetOwner() const {
		return _owner;
	}

	template <typename FunctorType, typename ParamVecType, int Args> WrapImpl;

// begin implement Bind and StaticBind methods
#define SAFE_OBEJCT_BIND_IMPL

#define PARAM_TYPENAME_LIST
#define PARAM_TYPE_LIST
#define PARAM_PASS_LIST
#define PARAM_CALL_LIST
#define PARAM_COUNT 0
#include "internal/bind_methods_impl.inl"
#undef PARAM_TYPENAME_LIST
#undef PARAM_TYPE_LIST
#undef PARAM_PASS_LIST
#undef PARAM_CALL_LIST
#undef PARAM_COUNT

#define PARAM_TYPENAME_LIST , typename Param1Type
#define PARAM_TYPE_LIST Param1Type
#define PARAM_PASS_LIST , Param1Type p1
#define PARAM_CALL_LIST , p1
#define PARAM_COUNT 1
#include "internal/bind_methods_impl.inl"
#undef PARAM_TYPENAME_LIST
#undef PARAM_TYPE_LIST
#undef PARAM_PASS_LIST
#undef PARAM_CALL_LIST
#undef PARAM_COUNT

#define PARAM_TYPENAME_LIST , typename Param1Type, typename Param2Type
#define PARAM_TYPE_LIST Param1Type, Param2Type
#define PARAM_PASS_LIST , Param1Type p1, Param2Type p2
#define PARAM_CALL_LIST , p1, p2
#define PARAM_COUNT 2
#include "internal/bind_methods_impl.inl"
#undef PARAM_TYPENAME_LIST
#undef PARAM_TYPE_LIST
#undef PARAM_PASS_LIST
#undef PARAM_CALL_LIST
#undef PARAM_COUNT

#define PARAM_TYPENAME_LIST , typename Param1Type, typename Param2Type, typename Param3Type
#define PARAM_TYPE_LIST Param1Type, Param2Type, Param3Type
#define PARAM_PASS_LIST , Param1Type p1, Param2Type p2, Param3Type p3
#define PARAM_CALL_LIST , p1, p2, p3
#define PARAM_COUNT 3
#include "internal/bind_methods_impl.inl"
#undef PARAM_TYPENAME_LIST
#undef PARAM_TYPE_LIST
#undef PARAM_PASS_LIST
#undef PARAM_CALL_LIST
#undef PARAM_COUNT

#define PARAM_TYPENAME_LIST , typename Param1Type, typename Param2Type, typename Param3Type, typename Param4Type
#define PARAM_TYPE_LIST Param1Type, Param2Type, Param3Type, Param4Type
#define PARAM_PASS_LIST , Param1Type p1, Param2Type p2, Param3Type p3, Param4Type p4
#define PARAM_CALL_LIST , p1, p2, p3, p4
#define PARAM_COUNT 4
#include "internal/bind_methods_impl.inl"
#undef PARAM_TYPENAME_LIST
#undef PARAM_TYPE_LIST
#undef PARAM_PASS_LIST
#undef PARAM_CALL_LIST
#undef PARAM_COUNT

#define PARAM_TYPENAME_LIST , typename Param1Type, typename Param2Type, typename Param3Type, typename Param4Type, typename Param5Type
#define PARAM_TYPE_LIST Param1Type, Param2Type, Param3Type, Param4Type, Param5Type
#define PARAM_PASS_LIST , Param1Type p1, Param2Type p2, Param3Type p3, Param4Type p4 , Param5Type p5
#define PARAM_CALL_LIST , p1, p2, p3, p4, p5
#define PARAM_COUNT 5
#include "internal/bind_methods_impl.inl"
#undef PARAM_TYPENAME_LIST
#undef PARAM_TYPE_LIST
#undef PARAM_PASS_LIST
#undef PARAM_CALL_LIST
#undef PARAM_COUNT

#define PARAM_TYPENAME_LIST , typename Param1Type, typename Param2Type, typename Param3Type, typename Param4Type, typename Param5Type, typename Param6Type
#define PARAM_TYPE_LIST Param1Type, Param2Type, Param3Type, Param4Type, Param5Type, Param6Type
#define PARAM_PASS_LIST , Param1Type p1, Param2Type p2, Param3Type p3, Param4Type p4, Param5Type p5, Param6Type p6
#define PARAM_CALL_LIST , p1, p2, p3, p4, p5, p6
#define PARAM_COUNT 6
#include "internal/bind_methods_impl.inl"
#undef PARAM_TYPENAME_LIST
#undef PARAM_TYPE_LIST
#undef PARAM_PASS_LIST
#undef PARAM_CALL_LIST
#undef PARAM_COUNT

#define PARAM_TYPENAME_LIST , typename Param1Type, typename Param2Type, typename Param3Type, typename Param4Type, typename Param5Type, typename Param6Type, typename Param7Type
#define PARAM_TYPE_LIST Param1Type, Param2Type, Param3Type, Param4Type, Param5Type, Param6Type, Param7Type
#define PARAM_PASS_LIST , Param1Type p1, Param2Type p2, Param3Type p3, Param4Type p4, Param5Type p5, Param6Type p6, Param7Type p7
#define PARAM_CALL_LIST , p1, p2, p3, p4, p5, p6, p7
#define PARAM_COUNT 7
#include "internal/bind_methods_impl.inl"
#undef PARAM_TYPENAME_LIST
#undef PARAM_TYPE_LIST
#undef PARAM_PASS_LIST
#undef PARAM_CALL_LIST
#undef PARAM_COUNT

#undef SAFE_OBEJCT_BIND_IMPL

// end implement Bind and StaticBind methods

	OwnerType _owner;
};


typedef SafeObjectImpl<SafeInvokerOwner, AliveTypeTag> Object;

typedef SafeObjectImpl<SafeInvokerOwner, RefCountTypeTag> RefCountObject;

}

}